package com.draven.mybatis.session;

import com.draven.mybatis.config.DravenConfig;
import com.draven.mybatis.executor.DravenExecutor;
import com.draven.mybatis.executor.DravenSimpleExecutor;
import com.draven.mybatis.mapping.DravenEnvironment;
import com.draven.mybatis.mapping.DravenMapperRegistry;
import com.draven.mybatis.transaction.DravenTransactionFactory;
import com.mysql.cj.jdbc.MysqlDataSource;
import org.apache.ibatis.binding.MapperRegistry;
import org.apache.ibatis.plugin.InterceptorChain;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.test.mapper.UserMapper;
import org.apache.ibatis.transaction.Transaction;


/**
 * mybatis   的配置类
 */

public class DravenConfiguration {
  private final static String id = "development";
  protected DravenEnvironment dravenEnvironment;
  protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
  protected final InterceptorChain interceptorChain = new InterceptorChain();
  protected final DravenMapperRegistry mapperRegistry = new DravenMapperRegistry(this);

  public DravenConfiguration() {
    iniDravenEnvironment();
    scanMapper();
  }

  void iniDravenEnvironment() {
    DravenTransactionFactory transactionFactory = new DravenTransactionFactory();
    MysqlDataSource dataSource = new MysqlDataSource();
    dataSource.setUser(DravenConfig.USERNAME);
    dataSource.setPassword(DravenConfig.PASSWORD);
    dataSource.setURL(DravenConfig.URL);
    this.dravenEnvironment = new DravenEnvironment(id, transactionFactory, dataSource);
    System.out.println("=============DravenConfiguration 初始化完成============");
  }

  void scanMapper() {
    mapperRegistry.addMapper(UserMapper.class);
    System.out.println("===============添加maper到容器=========");
  }

  public ExecutorType getDefaultExecutorType() {
    return defaultExecutorType;
  }

  public DravenEnvironment getDravenEnvironment() {
    return dravenEnvironment;
  }

  public DravenExecutor newExecutor(Transaction transaction, ExecutorType executorType) {

    DravenSimpleExecutor simpleExecutor = new DravenSimpleExecutor(this, transaction);

    return (DravenExecutor) interceptorChain.pluginAll(simpleExecutor);
  }

  public <T> T getMapper(Class<T> type, DravenSqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }
}
